<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
	<meta http-equiv="Cache-Control" content="no-siteapp" />

    <title>xmake-vscode插件开发过程记录</title>
    <meta name="description" content="最近打算给xmake写一些IDE和编辑器的集成插件，发现vscode的编辑器插件比较容易上手的，就先研究了下vscode的插件开发流程，并且完成了xmake-vscode插件的开发。我们先来看几张最后的效果图：语法高亮和自动补全状态栏">

    
    <meta name="keywords" content="xmake,vscode,插件开发,tboox" /> 

    <!-- qq oauth -->
    <meta property="qc:admins" content="5211601217706727767255" />

    <!--icon -->
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
    <link rel="icon" sizes="192x192" href="/static/img/nice-highres.png" />
	<link rel="apple-touch-icon-precomposed" href="/static/img/apple-touch-icon-57x57-precomposed.png" />
	<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/static/img/apple-touch-icon-72x72-precomposed.png" />
	<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/static/img/apple-touch-icon-114x114-precomposed.png" />
	<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/static/img/apple-touch-icon-144x144-precomposed.png" />
	<link rel="apple-touch-icon-precomposed" sizes="180x180" href="/static/img/retinahd_icon.png" />
	<meta name="msapplication-TileImage" content="/static/img/retinahd_icon.png" />
	
    <link rel="stylesheet" href=" /css/fontawesome/css/font-awesome.min.css ">
    <link rel="stylesheet" href=" /css/main.css ">
    <link rel="canonical" href="https://tboox.org/cn/2017/10/11/xmake-vscode/">
    <link rel="alternate" type="application/rss+xml" title="TBOOX Open Source Project" href="https://tboox.org/feed.xml ">
    <link rel="alternate" hreflang="en" href="https://tboox.org/" />
    <link rel="alternate" hreflang="zh-Hans" href="https://tboox.org/cn/" />

    <!-- css -->
    <link href="/css/reward.css" rel="stylesheet" type="text/css"> 




    <script type="text/javascript">
    function isPC(){    
        var userAgentInfo = navigator.userAgent;  
        var Agents = new Array("Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod");    
        var flag = true;    
        for (var v = 0; v < Agents.length; v++) {    
            if (userAgentInfo.indexOf(Agents[v]) > 0) { flag = false; break; }    
        }    
        return flag;    
    }
    </script>

<!-- baidu ads -->



    <!-- baidu ads -->

</head>


  <body>

    <header id="top">
    <div class="wrapper">
        <a href="/cn" class="brand">TBOOX</a>
        <button id="headerMenu" class="menu"><i class="fa fa-bars"></i></button>
        <nav id="headerNav">
            <ul>
                <li>
                    
                    <a href="/?lang=0">
                    
                        <i class="fa fa-home"></i>English
                    </a>
                </li>

                
                    
                    
                    <li>
                        
                            
                            <a href="/cn/project/">
                            
                        
                            <i class="fa fa-bookmark"></i>项目
                        </a>
                    </li>
                    
                    
                
                    
                    
                    
                
                    
                    
                    <li>
                        
                            
                            <a href="/cn/archive/">
                            
                        
                            <i class="fa fa-archive"></i>归档
                        </a>
                    </li>
                    
                    
                
                    
                    
                    
                
                    
                    
                    <li>
                        
                            
                            <a href="/cn/category/">
                            
                        
                            <i class="fa fa-th-list"></i>分类
                        </a>
                    </li>
                    
                    
                
                    
                    
                    
                
                    
                    
                    <li>
                        
                            
                            <a href="/cn/tag/">
                            
                        
                            <i class="fa fa-tags"></i>标记
                        </a>
                    </li>
                    
                    
                
                    
                    
                    
                
                    
                
                    
                    
                    <li>
                        
                            
                            <a href="/cn/docs/">
                            
                        
                            <i class="fa fa-book"></i>文档
                        </a>
                    </li>
                    
                    
                
                    
                    
                    
                
                    
                    
                    <li>
                        
                            
                            <a href="https://xmake.io/#/zh-cn/about/contact" target="_blank" >
                            
                        
                            <i class="fa fa-forumbee"></i>社区
                        </a>
                    </li>
                    
                    
                
                    
                    
                    
                
                    
                    
                    <li>
                        
                            
                            <a href="/cn/donation/">
                            
                        
                            <i class="fa fa-heart"></i>捐助
                        </a>
                    </li>
                    
                    
                
                    
                    
                    
                
                    
                    
                    <li>
                        
                            
                            <a href="/cn/about/">
                            
                        
                            <i class="fa fa-user"></i>关于
                        </a>
                    </li>
                    
                    
                
                    
                    
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                    
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
                    
                
            </ul>
        </nav>
    </div>
</header>



        <div class="page clearfix" post>
    <div class="left">
        <h1>xmake-vscode插件开发过程记录</h1>
        <div class="label">

            <div class="label-card">
                <i class="fa fa-calendar"></i>2017-10-11
            </div>

            <div class="label-card">
                
            </div>

            <div class="label-card">
                
            </div>

            <div class="label-card">
            


<!-- <span class="point">•</span> -->
<span class="categories">
  <i class="fa fa-th-list"></i>
  
    
        <a href="/category/#xmake" title="Category: xmake" rel="category">xmake</a>
    
  

  <!-- <span class="point">•</span> -->
</span>


            </div>

            <div class="label-card">
            
<!-- <span class="point">•</span> -->
<span class="pageTag">
  <i class="fa fa-tags"></i>
  
    
        <!--a href="/tag/#xmake" title="Tag: xmake" rel="tag">xmake</a-->
        <a href="/cn/tag/#xmake" title="Tag: xmake" rel="tag">xmake</a>&nbsp;
    
        <!--a href="/tag/#vscode" title="Tag: vscode" rel="tag">vscode</a-->
        <a href="/cn/tag/#vscode" title="Tag: vscode" rel="tag">vscode</a>&nbsp;
    
        <!--a href="/tag/#%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91" title="Tag: 插件开发" rel="tag">插件开发</a-->
        <a href="/cn/tag/#插件开发" title="Tag: 插件开发" rel="tag">插件开发</a>
    
  

</span>

            </div>

        </div>
        <hr>
        <article itemscope itemtype="http://schema.org/BlogPosting">
        <p>最近打算给<a href="https://github.com/xmake-io/xmake">xmake</a>写一些IDE和编辑器的集成插件，发现vscode的编辑器插件比较容易上手的，就先研究了下vscode的插件开发流程，并且完成了<a href="https://github.com/xmake-io/xmake-vscode">xmake-vscode</a>插件的开发。</p>

<p>我们先来看几张最后的效果图：</p>

<h2 id="语法高亮和自动补全">语法高亮和自动补全</h2>

<p><img src="/static/img/xmake/xmake-vscode-completion.gif" width="60%" /></p>

<h2 id="状态栏">状态栏</h2>

<p><img src="/static/img/xmake/xmake-vscode-statusbar.png" alt="statusbar" /></p>

<p>要实现上面的效果，其实并不复杂，首先我们先来简单介绍下，vscode的插件开发的基本流程：</p>

<h2 id="安装插件开发环境">安装插件开发环境</h2>

<h4 id="安装cnpm">安装cnpm</h4>

<p>由于国内环境比较复杂，直接用npm安装也许很慢或者访问不稳定，因此这里先安装了cnpm去默认使用淘宝的镜像源。</p>

<div class="language-console highlighter-rouge"><pre class="highlight"><code><span class="w">$ </span><span class="nc">npm</span><span class="kv"> install -g cnpm --registry=https://registry.npm.taobao.org
</span></code></pre>
</div>

<h4 id="创建空工程">创建空工程</h4>

<p>通过cnpm去安装yo工具，用来创建一个vscode插件的空工程</p>

<div class="language-console highlighter-rouge"><pre class="highlight"><code><span class="w">$ </span><span class="nc">cnpm</span><span class="kv"> install -g yo generator-code
</span><span class="w">$ </span><span class="nc">yo</span><span class="kv"> code
</span></code></pre>
</div>

<p>大体的源码结构如下：</p>

<p><img src="/static/img/xmake/xmake-vscode-yo-code.png" width="80%" /></p>

<p>选择创建项目后有四个输入和一个选择：</p>

<ul>
  <li>输入你扩展的名称 xmake-vscode</li>
  <li>输入一个标志（项目创建的文件名称用这个）xmake-vscode</li>
  <li>输入对这个扩展的描述</li>
  <li>输入以后要发布用到的一名称（和以后再发布时候有一个名字是对应上的）tboox</li>
  <li>是问你要不要创建一个git仓库用于版本管理</li>
</ul>

<p>创建完成后的空工程，我们可以用vscode直接打开，然后进行调试加载运行下：</p>

<p><img src="/static/img/xmake/xmake-vscode-debug.png" width="80%" /></p>

<p>加载起来后，敲F1打开命令窗口，运行默认的hello world测试命令：</p>

<p><img src="/static/img/xmake/xmake-vscode-hello1.png" width="80%" />
<img src="/static/img/xmake/xmake-vscode-hello2.png" width="80%" /></p>

<p>到此，一个简答的demo插件就搞定了，接下来我们简单介绍下如何发布这个插件到vscode的market上去。</p>

<h4 id="创建发布者">创建发布者</h4>

<p>首先我们需要在<a href="https://www.visualstudio.com/products/visual-studio-team-services-vs">marketplace.visualstudio.com</a>上注册一个账号，创建一个发布者，这里我取名为tboox</p>

<p>然后，我们需要在自己的账号里面，添加一个Personal Access Token（地址：<code class="highlighter-rouge">https://[your name].visualstudio.com/_details/security/tokens</code>，注意Token只显示一次，最好自己保存一份）</p>

<p>接着，我们安装下vsce这个工具，用于vscode的插件工程打包编译和发布。</p>

<div class="language-console highlighter-rouge"><pre class="highlight"><code><span class="w">$ </span><span class="nc">cnpm</span><span class="kv"> install -g vsce
</span></code></pre>
</div>

<p>安装好vsce后，我们先创建一个发布者，这里为tboox，输入刚刚market账号里面提供的token进行绑定。</p>

<div class="language-console highlighter-rouge"><pre class="highlight"><code><span class="w">$ </span><span class="nc">vsce</span><span class="kv"> create-publisher (publisher name)
</span></code></pre>
</div>

<h4 id="构建发布">构建发布</h4>

<p>最后，只需要通过下面命令进行打包或者发布就行了，如果仅仅打个本地包，拖入vscode加载测试，可以运行：</p>

<div class="language-console highlighter-rouge"><pre class="highlight"><code><span class="w">$ </span><span class="nc">vsce</span><span class="kv"> package
</span></code></pre>
</div>

<p>这将会生成一个类似<code class="highlighter-rouge">xmake-vscode-0.0.1.vslx</code>的插件包文件，用vscode可直接加载运行。</p>

<p>如果，我们已经开发完了插件，想要发布到market市场，可以执行：</p>

<div class="language-console highlighter-rouge"><pre class="highlight"><code><span class="w">$ </span><span class="nc">vsce</span><span class="kv"> publish [version]
</span></code></pre>
</div>

<p>这个时候，我们就可以在<a href="https://marketplace.visualstudio.com/items?itemName=tboox.xmake-vscode#overview">xmake-vscode on marketplace</a>上看到你的插件了，用户也可以直接通过vscode进行搜索和安装使用。</p>

<p><img src="/static/img/xmake/xmake-vscode-market.png" width="60%" /></p>

<h2 id="插件开发详解">插件开发详解</h2>

<h4 id="插件的加载机制">插件的加载机制</h4>

<p>插件通过工程根目录extension.json中配置的activationEvents进行触发，例如：</p>

<div class="language-json highlighter-rouge"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nt">"activationEvents"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
        </span><span class="s2">"workspaceContains:xmake.lua"</span><span class="p">,</span><span class="w">
        </span><span class="s2">"onCommand:xmake.sayHello"</span><span class="w">
    </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre>
</div>

<p>当vscode打开带有<code class="highlighter-rouge">xmake.lua</code>的目录或者执行<code class="highlighter-rouge">xmake.XXX</code>相关命令的时候，都会触发加载xmake-vscode插件，然后调用<code class="highlighter-rouge">src/extension.ts</code>中的activate入口函数，进行插件的加载和初始化。</p>

<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">export</span> <span class="kd">function</span> <span class="nx">activate</span><span class="p">(</span><span class="nx">context</span><span class="err">:</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">ExtensionContext</span><span class="p">)</span> <span class="p">{</span>

    <span class="kd">let</span> <span class="nx">disposable</span> <span class="o">=</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">commands</span><span class="p">.</span><span class="nx">registerCommand</span><span class="p">(</span><span class="s1">'xmake.sayHello'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nx">vscode</span><span class="p">.</span><span class="nb">window</span><span class="p">.</span><span class="nx">showInformationMessage</span><span class="p">(</span><span class="s1">'Hello XMake!'</span><span class="p">);</span>
    <span class="p">});</span>

    <span class="nx">context</span><span class="p">.</span><span class="nx">subscriptions</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">disposable</span><span class="p">);</span>
<span class="p">}</span>
</code></pre>
</div>

<p>上述代码，在加载插件的时候，注册<code class="highlighter-rouge">sayHello</code>命令，去显示<code class="highlighter-rouge">Hello XMake!</code>提示信息。</p>

<h4 id="创建自定义输出">创建自定义输出</h4>

<p>vscode通过创建OutputChannel来输出自己的日志信息，代码如下：</p>

<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">import</span> <span class="o">*</span> <span class="nx">as</span> <span class="nx">vscode</span> <span class="nx">from</span> <span class="s1">'vscode'</span><span class="p">;</span>

<span class="kd">let</span> <span class="nx">log</span> <span class="o">=</span> <span class="nx">vscode</span><span class="p">.</span><span class="nb">window</span><span class="p">.</span><span class="nx">createOutputChannel</span><span class="p">(</span><span class="s2">"xmake/log"</span><span class="p">);</span>
<span class="nx">log</span><span class="p">.</span><span class="nx">show</span><span class="p">();</span>
<span class="nx">log</span><span class="p">.</span><span class="nx">appendLine</span><span class="p">(</span><span class="s2">"hello xmake!"</span><span class="p">);</span>
</code></pre>
</div>

<p>在创建的时候可以指定一个label名，用于区分不同的输出通道，最后显示的结果如下：</p>

<p><img src="/static/img/xmake/xmake-vscode-channel.png" width="60%" /></p>

<p>需要注意的是，必须执行<code class="highlighter-rouge">log.show()</code>，输出才会被显示出来，并且输出行为是带缓存刷新的，并不会实时输出，也不支持色彩高亮输出。</p>

<h4 id="创建和控制终端">创建和控制终端</h4>

<p>之前，xmake-vscode就是采用channel的方式来输出xmake的构建信息，效果不是很理想，因此后来改用了终端直接执行的方式，可以看下下面的效果图：</p>

<p><img src="/static/img/xmake/xmake-vscode-build.gif" width="80%" /></p>

<p>那如何控制终端，执行自己的命令呢，其实也非常简单：</p>

<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kd">let</span> <span class="nx">terminal</span> <span class="o">=</span> <span class="nx">vscode</span><span class="p">.</span><span class="nb">window</span><span class="p">.</span><span class="nx">createTerminal</span><span class="p">({</span><span class="na">name</span><span class="p">:</span> <span class="s2">"xmake"</span><span class="p">});</span>
<span class="nx">terminal</span><span class="p">.</span><span class="nx">show</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
<span class="nx">terminal</span><span class="p">.</span><span class="nx">sendText</span><span class="p">(</span><span class="s2">"xmake"</span><span class="p">);</span>
</code></pre>
</div>

<p>上面的代码，通过创建一个label名为xmake的独立终端，然后发送执行命令：<code class="highlighter-rouge">xmake</code>，去让终端执行xmake进行项目的构建，当然如果要显示出来，还是要先调用下<code class="highlighter-rouge">terminal.show(true)</code>。</p>

<h4 id="添加和读取全局配置">添加和读取全局配置</h4>

<p>xmake-vscode里面增加了一些全局vscode配置项，用于控制xmake-vscode插件的行为，配置清单是在package.json文件中进行描述的，例如：</p>

<div class="language-json highlighter-rouge"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nt">"configuration"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nt">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"object"</span><span class="p">,</span><span class="w">
        </span><span class="nt">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"XMake configuration"</span><span class="p">,</span><span class="w">
        </span><span class="nt">"properties"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nt">"xmake.logLevel"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
                </span><span class="nt">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"string"</span><span class="p">,</span><span class="w">
                </span><span class="nt">"default"</span><span class="p">:</span><span class="w"> </span><span class="s2">"normal"</span><span class="p">,</span><span class="w">
                </span><span class="nt">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"The Log Level: normal/verbose/minimal"</span><span class="p">,</span><span class="w">
                </span><span class="nt">"enum"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
                    </span><span class="s2">"verbose"</span><span class="p">,</span><span class="w">
                    </span><span class="s2">"normal"</span><span class="p">,</span><span class="w">
                    </span><span class="s2">"minimal"</span><span class="w">
                </span><span class="p">]</span><span class="w">
            </span><span class="p">},</span><span class="w">
            </span><span class="nt">"xmake.buildDirectory"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
                </span><span class="nt">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"string"</span><span class="p">,</span><span class="w">
                </span><span class="nt">"default"</span><span class="p">:</span><span class="w"> </span><span class="s2">"${workspaceRoot}/build"</span><span class="p">,</span><span class="w">
                </span><span class="nt">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"The Build Output Directory"</span><span class="w">
            </span><span class="p">},</span><span class="w">
            </span><span class="nt">"xmake.androidNDKDirectory"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
                </span><span class="nt">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"string"</span><span class="p">,</span><span class="w">
                </span><span class="nt">"default"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
                </span><span class="nt">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"The Android NDK Directory"</span><span class="w">
            </span><span class="p">}</span><span class="w">
        </span><span class="p">}</span><span class="w">
    </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre>
</div>

<p>上述配置，增加了三个配置项，都在<code class="highlighter-rouge">xmake.</code>域下面，可在vscode配置中直接搜索xmake相关字样就能方便找到。</p>

<p><img src="/static/img/xmake/xmake-vscode-configure.png" width="90%" /></p>

<p>读取配置也很方便，只要获取xmake相关域配置，进行读取就行了：</p>

<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">const</span> <span class="nx">config</span> <span class="o">=</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">workspace</span><span class="p">.</span><span class="nx">getConfiguration</span><span class="p">(</span><span class="s1">'xmake'</span><span class="p">);</span>
<span class="nx">config</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s2">"buildDirectory"</span><span class="p">);</span>
</code></pre>
</div>

<h4 id="创建状态栏">创建状态栏</h4>

<p>状态栏上的按钮是可以响应之前创建的那些命令的，例如：<code class="highlighter-rouge">xmake.sayHello</code>等，下面我们在状态栏上创建一个debug按钮，用来调试运行xmake构建的程序：</p>

<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kd">let</span> <span class="nx">debugButton</span> <span class="o">=</span> <span class="nx">vscode</span><span class="p">.</span><span class="nb">window</span><span class="p">.</span><span class="nx">createStatusBarItem</span><span class="p">(</span><span class="nx">vscode</span><span class="p">.</span><span class="nx">StatusBarAlignment</span><span class="p">.</span><span class="nx">Left</span><span class="p">,</span> <span class="mf">4.5</span><span class="p">);</span>

<span class="nx">debugButton</span><span class="p">.</span><span class="nx">command</span> <span class="o">=</span> <span class="s1">'xmake.onDebug'</span><span class="p">;</span>
<span class="nx">debugButton</span><span class="p">.</span><span class="nx">text</span> <span class="o">=</span> <span class="err">`</span><span class="nx">$</span><span class="p">(</span><span class="nx">bug</span><span class="p">)</span><span class="err">`</span><span class="p">;</span>
<span class="nx">debugButton</span><span class="p">.</span><span class="nx">tooltip</span> <span class="o">=</span> <span class="s2">"Debug the given target"</span><span class="p">;</span>
<span class="nx">debugButton</span><span class="p">.</span><span class="nx">show</span><span class="p">();</span>
</code></pre>
</div>

<p>createStatusBarItem中第二个参数4.5用于控制按钮在状态栏上的布局顺序，创建好后，再设置下一些基础属性就行了，这里按钮的文本直接通过<code class="highlighter-rouge">$(bug)</code>设置了一个图标来显示，更加的直观。</p>

<p>更多vscode内置支持的图标，可以自己从<a href="https://octicons.github.com/">octicons</a>上面去找。</p>

<p>点击这个按钮，将会触发<code class="highlighter-rouge">xmake.onDebug</code>命令，然后在终端上执行<code class="highlighter-rouge">xmake run -d</code>命令，去运行调试程序。</p>

<p><img src="/static/img/xmake/xmake-vscode-debug.gif" width="60%" /></p>

<h4 id="添加选项输入列表">添加选项输入列表</h4>

<p>在<a href="https://github.com/xmake-io/xmake-vscode">xmake-vscode</a>的状态栏上，我们还增加了几个快速配置的状态按钮，用于快速切换不同的平台、架构、编译模式，例如：</p>

<p><img src="/static/img/xmake/xmake-vscode-configure.gif" width="60%" /></p>

<p>这个时候，需要有个选项选择列表的支持，在点击按钮后，列出可以选择的几个选项，然后选择切换，那如何创建这个选项列表呢，直接上代码：</p>

<div class="language-js highlighter-rouge"><pre class="highlight"><code>
<span class="c1">// 初始化选项列表清单</span>
<span class="kd">let</span> <span class="nx">items</span><span class="err">:</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">QuickPickItem</span><span class="p">[]</span> <span class="o">=</span> <span class="p">[];</span>
<span class="nx">items</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="na">label</span><span class="p">:</span> <span class="s2">"linux"</span><span class="p">,</span> <span class="na">description</span><span class="p">:</span> <span class="s2">"The Linux Platform"</span><span class="p">});</span>
<span class="nx">items</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="na">label</span><span class="p">:</span> <span class="s2">"macosx"</span><span class="p">,</span> <span class="na">description</span><span class="p">:</span> <span class="s2">"The MacOS Platform"</span><span class="p">});</span>
<span class="nx">items</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="na">label</span><span class="p">:</span> <span class="s2">"windows"</span><span class="p">,</span> <span class="na">description</span><span class="p">:</span> <span class="s2">"The Windows Platform"</span><span class="p">});</span>
<span class="nx">items</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="na">label</span><span class="p">:</span> <span class="s2">"android"</span><span class="p">,</span> <span class="na">description</span><span class="p">:</span> <span class="s2">"The Android Platform"</span><span class="p">});</span>
<span class="nx">items</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="na">label</span><span class="p">:</span> <span class="s2">"iphoneos"</span><span class="p">,</span> <span class="na">description</span><span class="p">:</span> <span class="s2">"The iPhoneOS Platform"</span><span class="p">});</span>
<span class="nx">items</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="na">label</span><span class="p">:</span> <span class="s2">"watchos"</span><span class="p">,</span> <span class="na">description</span><span class="p">:</span> <span class="s2">"The WatchOS Platform"</span><span class="p">});</span>
<span class="nx">items</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="na">label</span><span class="p">:</span> <span class="s2">"mingw"</span><span class="p">,</span> <span class="na">description</span><span class="p">:</span> <span class="s2">"The MingW Platform"</span><span class="p">});</span>
<span class="nx">items</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="na">label</span><span class="p">:</span> <span class="s2">"cross"</span><span class="p">,</span> <span class="na">description</span><span class="p">:</span> <span class="s2">"The Cross Platform"</span><span class="p">});</span>

<span class="c1">// 显示选项列表，提示用户选择</span>
<span class="kr">const</span> <span class="nx">chosen</span><span class="err">:</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">QuickPickItem</span><span class="o">|</span><span class="kc">undefined</span> <span class="o">=</span> <span class="nx">await</span> <span class="nx">vscode</span><span class="p">.</span><span class="nb">window</span><span class="p">.</span><span class="nx">showQuickPick</span><span class="p">(</span><span class="nx">items</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">chosen</span><span class="p">)</span> <span class="p">{</span>

    <span class="c1">// 获取选择后的结果，然后更新状态栏按钮文本</span>
    <span class="nx">platButton</span><span class="p">.</span><span class="nx">text</span> <span class="o">=</span> <span class="nx">chosen</span><span class="p">.</span><span class="nx">label</span><span class="p">;</span>
<span class="p">}</span>
</code></pre>
</div>

<h4 id="自定义语法高亮">自定义语法高亮</h4>

<p>语法高亮完全可以通过配置文件来搞定，不用写代码，当然也可以在代码中动态配置，这样稍微繁琐些。</p>

<p>xmake-vscode里面需要处理工程xmake.lua描述文件的语法高亮，因此这边在package.json里面先定义了一个叫xmake的语言类型，如果编辑器打开<code class="highlighter-rouge">xmake.lua</code>文件，就会对其进行语法高亮处理。</p>

<div class="language-json highlighter-rouge"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nt">"contributes"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nt">"languages"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
            </span><span class="p">{</span><span class="w">
                </span><span class="nt">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"xmake"</span><span class="p">,</span><span class="w">
                </span><span class="nt">"filenames"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
                    </span><span class="s2">"xmake.lua"</span><span class="w">
                </span><span class="p">],</span><span class="w">
                </span><span class="nt">"aliases"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
                    </span><span class="s2">"XMake"</span><span class="w">
                </span><span class="p">],</span><span class="w">
                </span><span class="nt">"configuration"</span><span class="p">:</span><span class="w"> </span><span class="s2">"./languages/xmake-configuration.json"</span><span class="w">
            </span><span class="p">}</span><span class="w">
        </span><span class="p">],</span><span class="w">
        </span><span class="nt">"grammars"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
            </span><span class="p">{</span><span class="w">
                </span><span class="nt">"language"</span><span class="p">:</span><span class="w"> </span><span class="s2">"xmake"</span><span class="p">,</span><span class="w">
                </span><span class="nt">"scopeName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"source.xmake"</span><span class="p">,</span><span class="w">
                </span><span class="nt">"path"</span><span class="p">:</span><span class="w"> </span><span class="s2">"./languages/xmake-grammars.json"</span><span class="w">
            </span><span class="p">}</span><span class="w">
        </span><span class="p">]</span><span class="w">
    </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre>
</div>

<p>跟语法高亮相关的描述，都放置在<code class="highlighter-rouge">/languages/xmake-grammars.json</code>中，用json来描述，我们也可以用xml的格式来描述，但是这样可读性不是很好。</p>

<p><code class="highlighter-rouge">xmake-grammars.json</code>中的描述规则，我们摘录自lua的grammars文件，因为<code class="highlighter-rouge">xmake.lua</code>本身就是基于lua语法的，例如，我们匹配<code class="highlighter-rouge">'xxx'</code>单引号字符串的规则，进行字符串的高亮输出。</p>

<div class="language-json highlighter-rouge"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nt">"begin"</span><span class="p">:</span><span class="w"> </span><span class="s2">"'"</span><span class="p">,</span><span class="w">
    </span><span class="nt">"beginCaptures"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nt">"0"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"punctuation.definition.string.begin.xmake"</span><span class="w">
        </span><span class="p">}</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="nt">"end"</span><span class="p">:</span><span class="w"> </span><span class="s2">"'"</span><span class="p">,</span><span class="w">
    </span><span class="nt">"endCaptures"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nt">"0"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"punctuation.definition.string.end.xmake"</span><span class="w">
        </span><span class="p">}</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"string.quoted.single.xmake"</span><span class="p">,</span><span class="w">
    </span><span class="nt">"patterns"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
        </span><span class="p">{</span><span class="w">
            </span><span class="nt">"include"</span><span class="p">:</span><span class="w"> </span><span class="s2">"#escaped_char"</span><span class="w">
        </span><span class="p">}</span><span class="w">
    </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre>
</div>

<h4 id="自动补全的实现">自动补全的实现</h4>

<p>代码的自动提示和补全比较麻烦下，需要写个自定义的class，通过languages进行注册：</p>

<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="nx">vscode</span><span class="p">.</span><span class="nx">languages</span><span class="p">.</span><span class="nx">registerCompletionItemProvider</span><span class="p">(</span><span class="s2">"xmake"</span><span class="p">,</span> <span class="k">new</span> <span class="nx">Completion</span><span class="p">());</span>
</code></pre>
</div>

<p>这里我们定义了一个Completion类，注册到xmake语言上去，xmake语言定义，就是刚才讲的在package.json中的配置。</p>

<p>然后我们实现下这个Completion类：</p>

<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">export</span> <span class="kr">class</span> <span class="nx">Completion</span> <span class="kr">implements</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">CompletionItemProvider</span> <span class="p">{</span>

    <span class="c1">// 匹配当前输入，提供需要补全的候选文本列表</span>
    <span class="kr">public</span> <span class="nx">provideCompletionItems</span><span class="p">(</span><span class="nb">document</span><span class="err">:</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">TextDocument</span><span class="p">,</span> <span class="nx">position</span><span class="err">:</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">Position</span><span class="p">,</span> <span class="nx">token</span><span class="err">:</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">CancellationToken</span><span class="p">)</span><span class="err">:</span> <span class="nx">Thenable</span><span class="o">&lt;</span><span class="nx">vscode</span><span class="p">.</span><span class="nx">CompletionItem</span><span class="p">[]</span><span class="o">&gt;</span> <span class="p">{</span>

        <span class="c1">// 获取当前输入的单词文本</span>
        <span class="kd">let</span> <span class="nx">wordAtPosition</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getWordRangeAtPosition</span><span class="p">(</span><span class="nx">position</span><span class="p">);</span>
        <span class="kd">var</span> <span class="nx">currentWord</span> <span class="o">=</span> <span class="s1">''</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">(</span><span class="nx">wordAtPosition</span> <span class="o">&amp;&amp;</span> <span class="nx">wordAtPosition</span><span class="p">.</span><span class="nx">start</span><span class="p">.</span><span class="nx">character</span> <span class="o">&lt;</span> <span class="nx">position</span><span class="p">.</span><span class="nx">character</span><span class="p">)</span> <span class="p">{</span>
            <span class="kd">var</span> <span class="nx">word</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getText</span><span class="p">(</span><span class="nx">wordAtPosition</span><span class="p">);</span>
            <span class="nx">currentWord</span> <span class="o">=</span> <span class="nx">word</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">position</span><span class="p">.</span><span class="nx">character</span> <span class="o">-</span> <span class="nx">wordAtPosition</span><span class="p">.</span><span class="nx">start</span><span class="p">.</span><span class="nx">character</span><span class="p">);</span>
        <span class="p">}</span>

        <span class="c1">// 猜测匹配结果，返回候选列表</span>
        <span class="k">return</span> <span class="k">new</span> <span class="nx">Promise</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="p">{</span>
            <span class="nx">Promise</span><span class="p">.</span><span class="nx">all</span><span class="p">([</span>
                <span class="nx">getLuaKeywordsSuggestions</span><span class="p">(</span><span class="nx">currentWord</span><span class="p">),</span>
                <span class="nx">getXMakeCommandsSuggestions</span><span class="p">(</span><span class="nx">currentWord</span><span class="p">)</span>
            <span class="p">]).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">results</span><span class="p">)</span> <span class="p">{</span>
                <span class="kd">var</span> <span class="nx">suggestions</span> <span class="o">=</span> <span class="nb">Array</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">concat</span><span class="p">.</span><span class="nx">apply</span><span class="p">([],</span> <span class="nx">results</span><span class="p">);</span>
                <span class="nx">resolve</span><span class="p">(</span><span class="nx">suggestions</span><span class="p">);</span>
            <span class="p">}).</span><span class="k">catch</span><span class="p">(</span><span class="nx">err</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="nx">reject</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span> <span class="p">});</span>
        <span class="p">});</span>
    <span class="p">}</span>

    <span class="c1">// 这里可以对刚刚返回的候选文本列表在做二次处理，例如：增加详细的文档描述信息</span>
    <span class="kr">public</span> <span class="nx">resolveCompletionItem</span><span class="p">(</span><span class="na">item</span><span class="p">:</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">CompletionItem</span><span class="p">,</span> <span class="na">token</span><span class="p">:</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">CancellationToken</span><span class="p">):</span> <span class="nx">Thenable</span><span class="o">&lt;</span><span class="nx">vscode</span><span class="p">.</span><span class="nx">CompletionItem</span><span class="o">&gt;</span> <span class="p">{</span>
        
        <span class="c1">// 对每个候选文本增加文档描述</span>
        <span class="k">return</span> <span class="k">new</span> <span class="nx">Promise</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="p">{</span> 
            <span class="nx">item</span><span class="p">.</span><span class="nx">documentation</span> <span class="o">=</span> <span class="s2">"xxxxxxxxxxx"</span><span class="p">;</span>
            <span class="nx">resolve</span><span class="p">(</span><span class="nx">item</span><span class="p">);</span>
         <span class="p">});</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
</div>

<p>这部分代码比较多，就不完全贴出来了，完整实现，可参考：<a href="https://github.com/xmake-io/xmake-vscode/blob/master/src/completion.ts">completion.ts</a></p>

<p><img src="/static/img/xmake/xmake-vscode-completion.gif" width="60%" /></p>

<h4 id="错误和警告输出解析">错误和警告输出解析</h4>

<p>当编译出错或者出现警告信息的时候，xmake-vscode会自动提取解析编译器的错误信息，然后显示到vscode的问题列表中，并提供代码行的跳转支持。</p>

<p><img src="/static/img/xmake/xmake-vscode-problem.gif" width="60%" /></p>

<p>这里使用的是<code class="highlighter-rouge">vscode.languages.createDiagnosticCollection</code>来创建显示问题列表：</p>

<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">export</span> <span class="kr">class</span> <span class="nx">ProblemList</span> <span class="kr">implements</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">Disposable</span> <span class="p">{</span>

    <span class="c1">// the diagnostic collection</span>
    <span class="kr">private</span> <span class="nx">_diagnosticCollection</span><span class="err">:</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">DiagnosticCollection</span><span class="p">;</span>

    <span class="c1">// the constructor</span>
    <span class="nx">constructor</span><span class="p">()</span> <span class="p">{</span>

        <span class="c1">// init diagnostic collection</span>
        <span class="k">this</span><span class="p">.</span><span class="nx">_diagnosticCollection</span> <span class="o">=</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">languages</span><span class="p">.</span><span class="nx">createDiagnosticCollection</span><span class="p">(</span><span class="s2">"build"</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// dispose</span>
    <span class="kr">public</span> <span class="nx">dispose</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">this</span><span class="p">.</span><span class="nx">_diagnosticCollection</span><span class="p">.</span><span class="nx">dispose</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="c1">// clear problems </span>
    <span class="kr">public</span> <span class="nx">clear</span><span class="p">()</span> <span class="p">{</span>
        
        <span class="c1">// clear the previous problems first</span>
        <span class="k">this</span><span class="p">.</span><span class="nx">_diagnosticCollection</span><span class="p">.</span><span class="nx">clear</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="c1">// diagnose problems from the current logfile</span>
    <span class="kr">public</span> <span class="nx">diagnose</span><span class="p">(</span><span class="nx">logfile</span><span class="err">:</span> <span class="nx">string</span><span class="p">)</span> <span class="p">{</span>
        
        <span class="c1">// clear the previous problems first</span>
        <span class="k">this</span><span class="p">.</span><span class="nx">_diagnosticCollection</span><span class="p">.</span><span class="nx">clear</span><span class="p">();</span>

        <span class="c1">// exists logfile?</span>
        <span class="k">if</span> <span class="p">(</span><span class="nx">logfile</span><span class="p">)</span> <span class="p">{</span>

            <span class="kr">const</span> <span class="nx">isWin</span> <span class="o">=</span> <span class="nx">os</span><span class="p">.</span><span class="nx">platform</span><span class="p">()</span> <span class="o">==</span> <span class="s2">"win32"</span><span class="p">;</span>
            <span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span><span class="p">(</span><span class="nx">logfile</span><span class="p">,</span> <span class="nx">isWin</span><span class="p">?</span> <span class="kc">null</span> <span class="p">:</span> <span class="s2">"utf8"</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">content</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
                    
                <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">err</span> <span class="o">&amp;&amp;</span> <span class="nx">content</span><span class="p">)</span> <span class="p">{</span>
                    
                    <span class="c1">// 处理msvc输出的gbk编码文件</span>
                    <span class="kd">let</span> <span class="nx">text</span> <span class="o">=</span> <span class="nx">content</span><span class="p">;</span>
                    <span class="k">if</span> <span class="p">(</span><span class="nx">isWin</span><span class="p">)</span> <span class="p">{</span>
                        <span class="nx">text</span> <span class="o">=</span> <span class="nx">encoding</span><span class="p">.</span><span class="nx">convert</span><span class="p">(</span><span class="nx">content</span><span class="p">,</span> <span class="s2">"utf8"</span><span class="p">,</span> <span class="s2">"gbk"</span><span class="p">).</span><span class="nx">toString</span><span class="p">();</span>
                    <span class="p">}</span>

                    <span class="c1">// 用于解析gcc/clang的编译输出</span>
                    <span class="kr">const</span> <span class="na">rOutputGcc</span><span class="p">:</span> <span class="nb">RegExp</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="s2">"^(error: )?(.*?):([0-9]*):([0-9]*): (.*?): (.*)$"</span><span class="p">);</span>
                    
                    <span class="c1">// 用于解析msvc的编译输出</span>
                    <span class="kr">const</span> <span class="na">rOutputMsvc</span><span class="p">:</span> <span class="nb">RegExp</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="s2">"(.*?)\\(([0-9]*)\\): (.*?) .*?: (.*)"</span><span class="p">);</span>                    

                    <span class="c1">// init diagnostics map</span>
                    <span class="kd">let</span> <span class="na">diagnosticsMap</span><span class="p">:</span> <span class="nx">Map</span><span class="o">&lt;</span><span class="nx">string</span><span class="p">,</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">Diagnostic</span><span class="p">[]</span><span class="o">&gt;</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Map</span><span class="p">();</span>
    
                    <span class="c1">// 解析提取每行的错误信息</span>
                    <span class="nx">text</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s2">"\n"</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">textLine</span> <span class="o">=&gt;</span> <span class="p">{</span>
                        <span class="k">if</span> <span class="p">(</span><span class="nx">textLine</span><span class="p">)</span> <span class="p">{</span>

                            <span class="c1">// parse warning and error from the given text line</span>
                            <span class="kd">let</span> <span class="na">matches</span><span class="p">:</span> <span class="nx">RegExpExecArray</span> <span class="o">=</span> <span class="nx">isWin</span><span class="p">?</span> <span class="nx">rOutputMsvc</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">textLine</span><span class="p">)</span> <span class="p">:</span> <span class="nx">rOutputGcc</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">textLine</span><span class="p">);</span>
                            <span class="k">if</span> <span class="p">(</span><span class="nx">matches</span><span class="p">)</span> <span class="p">{</span> 

                                <span class="c1">// 解析提示中代码行和文件位置</span>
                                <span class="kd">let</span> <span class="nx">file</span> <span class="o">=</span> <span class="s2">""</span><span class="p">;</span>
                                <span class="kd">let</span> <span class="nx">line</span> <span class="o">=</span> <span class="s2">"0"</span><span class="p">;</span>
                                <span class="kd">let</span> <span class="nx">column</span> <span class="o">=</span> <span class="s2">"0"</span><span class="p">;</span>
                                <span class="kd">let</span> <span class="nx">kind</span> <span class="o">=</span> <span class="s2">"error"</span><span class="p">;</span>
                                <span class="kd">let</span> <span class="nx">message</span> <span class="o">=</span> <span class="s2">""</span><span class="p">;</span>
                                <span class="k">if</span> <span class="p">(</span><span class="nx">isWin</span><span class="p">)</span> <span class="p">{</span>

                                    <span class="nx">file</span> <span class="o">=</span> <span class="nx">matches</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">trim</span><span class="p">();</span>
                                    <span class="nx">line</span> <span class="o">=</span> <span class="nx">matches</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nx">trim</span><span class="p">();</span>
                                    <span class="nx">kind</span> <span class="o">=</span> <span class="nx">matches</span><span class="p">[</span><span class="mi">3</span><span class="p">].</span><span class="nx">toLocaleLowerCase</span><span class="p">().</span><span class="nx">trim</span><span class="p">();</span>
                                    <span class="nx">message</span> <span class="o">=</span> <span class="nx">matches</span><span class="p">[</span><span class="mi">4</span><span class="p">].</span><span class="nx">trim</span><span class="p">();</span>

                                <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>

                                    <span class="nx">file</span> <span class="o">=</span> <span class="nx">matches</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nx">trim</span><span class="p">();</span>
                                    <span class="nx">line</span> <span class="o">=</span> <span class="nx">matches</span><span class="p">[</span><span class="mi">3</span><span class="p">].</span><span class="nx">trim</span><span class="p">();</span>
                                    <span class="nx">column</span> <span class="o">=</span> <span class="nx">matches</span><span class="p">[</span><span class="mi">4</span><span class="p">].</span><span class="nx">trim</span><span class="p">();</span>
                                    <span class="nx">kind</span> <span class="o">=</span> <span class="nx">matches</span><span class="p">[</span><span class="mi">5</span><span class="p">].</span><span class="nx">toLocaleLowerCase</span><span class="p">().</span><span class="nx">trim</span><span class="p">();</span>
                                    <span class="nx">message</span> <span class="o">=</span> <span class="nx">matches</span><span class="p">[</span><span class="mi">6</span><span class="p">].</span><span class="nx">trim</span><span class="p">();</span>
                                <span class="p">}</span>

                                <span class="c1">// get uri of file</span>
                                <span class="kd">let</span> <span class="na">uri</span><span class="p">:</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">Uri</span> <span class="o">=</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">Uri</span><span class="p">.</span><span class="nx">file</span><span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">isAbsolute</span><span class="p">(</span><span class="nx">file</span><span class="p">)?</span> <span class="nx">file</span> <span class="p">:</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">config</span><span class="p">.</span><span class="nx">workingDirectory</span><span class="p">,</span> <span class="nx">file</span><span class="p">));</span>

                                <span class="c1">// get diagnostics of this file</span>
                                <span class="kd">let</span> <span class="na">diagnostics</span><span class="p">:</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">Diagnostic</span><span class="p">[]</span> <span class="o">=</span> <span class="nx">diagnosticsMap</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">uri</span><span class="p">.</span><span class="nx">fsPath</span><span class="p">);</span>                      

                                <span class="c1">// 是错误还是警告？</span>
                                <span class="kd">let</span> <span class="na">severity</span><span class="p">:</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">DiagnosticSeverity</span> <span class="o">=</span> <span class="p">{</span><span class="na">error</span><span class="p">:</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">DiagnosticSeverity</span><span class="p">.</span><span class="nb">Error</span><span class="p">,</span> <span class="na">warning</span><span class="p">:</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">DiagnosticSeverity</span><span class="p">.</span><span class="nx">Warning</span><span class="p">}[</span><span class="nx">kind</span><span class="p">];</span>
                                <span class="k">if</span> <span class="p">(</span><span class="nx">severity</span> <span class="o">!=</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">DiagnosticSeverity</span><span class="p">.</span><span class="nb">Error</span> <span class="o">&amp;&amp;</span> <span class="nx">severity</span> <span class="o">!=</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">DiagnosticSeverity</span><span class="p">.</span><span class="nx">Warning</span><span class="p">)</span> <span class="p">{</span>
                                    <span class="nx">severity</span> <span class="o">=</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">DiagnosticSeverity</span><span class="p">.</span><span class="nb">Error</span><span class="p">;</span>
                                <span class="p">}</span>

                                <span class="c1">// 定位错误行和列位置</span>
                                <span class="kd">let</span> <span class="nx">startLine</span> <span class="o">=</span> <span class="nb">Number</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>
                                <span class="kd">let</span> <span class="nx">startColumn</span> <span class="o">=</span> <span class="nb">Number</span><span class="p">(</span><span class="nx">column</span><span class="p">);</span>
                                <span class="k">if</span> <span class="p">(</span><span class="nx">startLine</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="nx">startLine</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span>
                                <span class="k">if</span> <span class="p">(</span><span class="nx">startColumn</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="nx">startColumn</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span>

                                <span class="c1">// get end line and column</span>
                                <span class="kd">let</span> <span class="nx">endLine</span> <span class="o">=</span> <span class="nx">startLine</span><span class="p">;</span>
                                <span class="kd">let</span> <span class="nx">endColumn</span> <span class="o">=</span> <span class="nx">startColumn</span><span class="p">;</span>

                                <span class="c1">// init range</span>
                                <span class="kd">let</span> <span class="nx">range</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">Range</span><span class="p">(</span><span class="nx">startLine</span><span class="p">,</span> <span class="nx">startColumn</span><span class="p">,</span> <span class="nx">endLine</span><span class="p">,</span> <span class="nx">endColumn</span><span class="p">);</span>
                                
                                <span class="c1">// 添加一个问题描述</span>
                                <span class="kd">let</span> <span class="nx">diagnostic</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">Diagnostic</span><span class="p">(</span><span class="nx">range</span><span class="p">,</span> <span class="nx">message</span><span class="p">,</span> <span class="nx">severity</span><span class="p">);</span>
                                <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">diagnostics</span><span class="p">)</span> <span class="p">{</span>
                                    <span class="nx">diagnostics</span> <span class="o">=</span> <span class="p">[];</span>
                                    <span class="nx">diagnosticsMap</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">uri</span><span class="p">.</span><span class="nx">fsPath</span><span class="p">,</span> <span class="nx">diagnostics</span><span class="p">);</span>
                                <span class="p">}</span>
                                <span class="nx">diagnostics</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">diagnostic</span><span class="p">);</span>                         
                            <span class="p">}</span>
                        <span class="p">}</span>
                    <span class="p">});</span>

                    <span class="c1">// 更新显示问题列表</span>
                    <span class="nx">diagnosticsMap</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="na">diagnostics</span><span class="p">:</span> <span class="nx">vscode</span><span class="p">.</span><span class="nx">Diagnostic</span><span class="p">[],</span> <span class="na">fsPath</span><span class="p">:</span><span class="nx">string</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
                        <span class="k">this</span><span class="p">.</span><span class="nx">_diagnosticCollection</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">vscode</span><span class="p">.</span><span class="nx">Uri</span><span class="p">.</span><span class="nx">file</span><span class="p">(</span><span class="nx">fsPath</span><span class="p">),</span> <span class="nx">diagnostics</span><span class="p">);</span>
                    <span class="p">});</span>
                <span class="p">}</span>
                <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
                    <span class="nx">log</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">err</span><span class="p">.</span><span class="nx">message</span><span class="p">);</span>
                <span class="p">}</span> 
            <span class="p">});</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
</div>

<h2 id="结语">结语</h2>

<p>本文讲述的一些vscode插件代码都来自<a href="https://github.com/xmake-io/xmake-vscode">xmake-vscode</a>，有兴趣的同学可以直接参考源码，写个自己的插件。</p>

        </article>
        <hr>

        <!-- baidu ads -->
        

        <!-- reward -->
        <div style="text-align: center;">
            <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
              <span>赏</span>
            </button>
            <div id="QR" style="display: none;">
                <div id="wechat" style="display: inline-block">
                  <img id="wechat_qr" src="/static/img/weixin.png" alt="WeChat Pay"/>
                  <p>微信打赏</p>
                </div>
                <div id="alipay" style="display: inline-block">
                  <img id="alipay_qr" src="/static/img/alipay.png" alt="Alipay"/>
                  <p>支付宝打赏</p>
                </div>
            </div>
        </div>

        
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
            
                
            
        
            
            
                
            
        
            
            
                
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
            
            
                
            
        
            
        
        

        
        
            
        
            
            
            
                
                    
                        
                        <h2 id="similar_posts">相关文章</h2>
                        <ul>
                        
                        <li class="relatedPost">
                            <a href="/cn/2021/12/17/xmake-update-v2.6.2/">xmake v2.6.2 发布，新增 Linux 内核驱动模块构建支持
                            
                            </a>
                        </li>
                        
                        
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
            
        
            
        
            
            
            
                
                    
                        
                        <li class="relatedPost">
                            <a href="/cn/2021/12/03/xmake-update-v2.6.1/">xmake v2.6.1 发布，使用 Lua5.4 运行时，Rust 和 C++ 混合编译支持
                            
                            </a>
                        </li>
                        
                        
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
            
        
            
        
            
            
            
                
                    
                        
                        <li class="relatedPost">
                            <a href="/cn/2021/10/30/xmake-update-v2.5.9/">xmake v2.5.9 发布，改进 C++20 模块，并支持 Nim, Keil MDK 和 Unity Build
                            
                            </a>
                        </li>
                        
                        
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
            
        
            
        
            
            
            
                
                    
                        
                        <li class="relatedPost">
                            <a href="/cn/2021/10/08/xmake-update-v2.5.8/">xmake v2.5.8 发布，新增 Pascal/Swig 程序和 Lua53 运行时支持
                            
                            </a>
                        </li>
                        
                        
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
            
        
            
        
            
            
            
                
                    
                        
                        <li class="relatedPost">
                            <a href="/cn/2021/08/29/xmake-update-v2.5.7/">xmake v2.5.7 发布，包依赖锁定和 Vala/Metal 语言编译支持
                            
                            </a>
                        </li>
                        
                        
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
                
                    
                
                    
                
                    
                
            
            
        
        
            </ul>
        

        <div class="post-recent">
    <div class="pre">

        

        

        
        
        <p><strong>上一篇</strong> <a href="/cn/2017/09/28/xmake-sourcecode-arch/">xmake 源码架构剖析</a></p>
        
    </div>

    <div class="nex">

        

        

        
        
        <p><strong>下一篇</strong> <a href="/cn/2017/10/13/update-v2.1.7/">xmake v2.1.7版本发布，稳定性修复和细节改进</a></p>
        
    </div>
</div>


        <h2 id="comments">评论</h2>
        






<div id="gitalk-container"></div>
<link rel="stylesheet" href="/css/gitalk.css">
<script src="/js/gitalk.min.js"></script>

<script>
const gitalk = new Gitalk({
  clientID: '73946dc1d9e2276ad0da',
  clientSecret: '12a3cb94361ba3ebc6ecb68cf80d592bfaa8106d',
  repo: 'tboox.github.io',
  owner: 'waruqi',
  admin: ['waruqi'],
  id: location.pathname,       
  language: 'zh-CN',
  distractionFreeMode: false  
})

gitalk.render('gitalk-container')
</script>





    </div>
    <button class="anchor"><i class="fa fa-anchor"></i></button>
    <div class="right">
        <div class="wrap">

            <!-- codefund ads -->
            

            <!-- Content -->
            <div class="side content">
                <div>
                    内容
                </div>
                <ul id="content-side" class="content-ul">
                    <li><a href="#english">English</a></li>
                    <li><a href="#similar_posts">相关文章</a></li>
                    <li><a href="#comments">评论</a></li>
                </ul>
            </div>


            <!-- baidu ads -->
            
            
            <br>
            <div class="side">
                <div>
                    <i class="fa fa-external-link"></i>
                    链接
                </div>
                <ul class="content-ul">
                  <li><a href="http://github.com/waruqi/tbox">tbox</a></li>
                  <li><a href="http://www.xmake.io">xmake</a></li>
                  <li><a href="https://github.com/waruqi">github</a></li>
                </ul>
            </div> 

            <!-- xmake courses -->
            <br>
            <div class="side">
                <div>
                    <i class="fa fa-external-link"></i>
                    xmake 入门课程
                </div>
                <a href="https://xmake.io/#/zh-cn/about/course" target="_blank">
                <img src="/static/img/xmake-course.png" alt="course" width="256" height="193">
                </a>
            </div>

            <!-- qqgroup -->
            <br>
            <div class="side">
                <div>
                    <i class="fa fa-external-link"></i>
                    技术交流群（QQ）
                </div>
                <img src="/static/img/qqgroup.png" alt="qqgroup" width="256" height="284">
            </div> 

            <!-- google ads -->
            

            <!-- baidu ads -->
            

        </div>
    </div>

    <!-- baidu ads -->
    
</div>
<script>
/**
 * target _blank
 */
(function() {
    var aTags = document.querySelectorAll('article a:not([id])')
    for (var i = 0; i < aTags.length; i++) {
        aTags[i].setAttribute('target', '_blank')
    }
}());
</script>
<script src="/js/pageContent.js " charset="utf-8"></script>



    <footer class="site-footer">
    <div class="wrapper">
        <p class="description">
             Copyright (c) 2016-2020 tboox.org 
        </p>
        <p class="contact">
            
            <a href="https://github.com/waruqi" title="GitHub"><i class="fa fa-github" aria-hidden="true"></i></a> 
             
            
            <a href="mailto:waruqi@gmail.com" title="email"><i class="fa fa-envelope-o" aria-hidden="true"></i></a> 
            
            
            <a href="https://twitter.com/waruqi" title="Twitter"><i class="fa fa-twitter" aria-hidden="true"></i></a> 
            
            <a href="/feed.xml" title="feed"><i class="fa fa-feed" aria-hidden="true"></i></a> 
        </p>
        <p class="power">
            <span>
                Site powered by <a href="https://jekyllrb.com/">Jekyll</a> & <a href="https://github.com/Gaohaoyang">HyG</a> & <a href="https://pages.github.com/">Github Pages</a>.
            </span>
        </p>
    </div>
</footer>

    <div class="back-to-top">
    <a href="#top" class="scroll">
        <i class="fa fa-arrow-up" aria-hidden="true"></i>
    </a>
</div>

    <script src=" /js/main.js " charset="utf-8"></script>
    <script src=" /js/scroll.min.js " charset="utf-8"></script>
  </body>

</html>
